
#include <sys_config.h>
#include <basic_types.h>
#include <mediatypes.h>
#include <api/libc/alloc.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <osal/osal.h>
#include <hld/hld_dev.h>
#include <hld/dsc/dsc.h>


#define offsetof(type, f) ((unsigned long) \
((char *)&((type *)0)->f - (char *)(type *)0))
#define TS_MAX_SIZE  0x10000  //64k
#define PURE_DATA_MAX_SIZE  0x4000000  //64k

#define INVALID_DSC_SUB_DEV_ID			0xff
#define INVALID_DSC_STREAM_ID			0xff

#ifdef DUAL_ENABLE
#include <modules.h>

enum HLD_DSC_FUNC{
    /*DES*/
    FUNC_DES_OPEN = 0,
    FUNC_DES_CLOSE,
    FUNC_DES_DECRYPT,
    FUNC_DES_ENCRYPT,
    FUNC_DES_IOCTL,
    /*AES*/
    FUNC_AES_OPEN  ,
    FUNC_AES_CLOSE,
    FUNC_AES_DECRYPT,
    FUNC_AES_ENCRYPT,
    FUNC_AES_IOCTL,
    /*CSA*/
    FUNC_CSA_OPEN  ,
    FUNC_CSA_CLOSE,
    FUNC_CSA_DECRYPT,
    FUNC_CSA_IOCTL,
    /*SHA*/
    FUNC_SHA_OPEN  ,
    FUNC_SHA_CLOSE,
    FUNC_SHA_DIGEST,
    FUNC_SHA_IOCTL,

    FUNC_DSC_IOCTL,
    FUNC_DES_DECRYPT_CW_DATA,
    FUNC_TRIG_RAM_MON,
    FUNC_DEENCRYPT,
    FUNC_GET_FREE_STREAM_ID,
    FUNC_SET_STREAM_ID_IDLE,
    FUNC_GET_FREE_SUB_DEVICE_ID,
    FUNC_SET_SUB_DEVICE_ID_IDLE,
    FUNC_SET_STREAM_ID_USED,
    FUNC_SET_SUB_DEVICE_ID_USED,
    FUNC_DEAL_QUANTUM_MIXED_TS,
};

#ifndef _HLD_DSC_REMOTE


UINT32 hld_dsc_entry[] = 
{
    (UINT32)des_open,
    (UINT32)des_close,
    (UINT32)des_decrypt_cts,
    (UINT32)des_encrypt,
    (UINT32)des_ioctl,

    (UINT32)aes_open,
    (UINT32)aes_close,
    (UINT32)aes_decrypt_cts,
    (UINT32)aes_encrypt,
    (UINT32)aes_ioctl,

    (UINT32)csa_open,
    (UINT32)csa_close,
    (UINT32)csa_decrypt,
    (UINT32)csa_ioctl,

    (UINT32)sha_open,
    (UINT32)sha_close,
    (UINT32)sha_digest,
    (UINT32)sha_ioctl,
    (UINT32)dsc_ioctl,

    (UINT32)dsc_des_decrypt_cw_data,
    (UINT32)trig_ram_mon,
    (UINT32)DeEncrypt,
    (UINT32)dsc_get_free_stream_id,
    (UINT32)dsc_set_stream_id_idle, 
    (UINT32)dsc_get_free_sub_device_id,
    (UINT32)dsc_set_sub_device_id_idle,
    (UINT32)dsc_set_stream_id_used,
    (UINT32)dsc_set_sub_device_id_used,
    (UINT32)dsc_deal_quantum_for_mixed_ts,
};

void hld_dsc_callee(UINT8 *msg)
{
    
    OS_hld_callee(hld_dsc_entry, msg);
}
#endif  /*_HLD_DSC_REMOTE*/

#ifdef _HLD_DSC_REMOTE
#define DSC_NPARA(x) ((HLD_DSC_MODULE<<24)|(x<<16))

UINT32 des_io_control[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, 0),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 aes_io_control[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, 0),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 csa_io_control[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, 0),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 sha_io_control[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, 0),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 dsc_io_control[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, 0),
  1, DESC_P_PARA(0, 2, 0), 
  //desc of pointer ret
  0,                          
  0,
};

UINT32 dsc_io_control_1[] = 
{ //desc of pointer para
  9, DESC_OUTPUT_STRU(0, sizeof(KEY_PARAM)), DESC_STATIC_STRU(1, 0),\
  	 DESC_STATIC_STRU(2, 4*sizeof(AES_KEY_PARAM)), DESC_STATIC_STRU(3, 4*sizeof(CSA_KEY_PARAM)),\
  	 DESC_STATIC_STRU(4, 4*sizeof(DES_KEY_PARAM)), DESC_STATIC_STRU(5, 4*sizeof(AES_IV_INFO)),\
  	 DESC_STATIC_STRU(6, 4*sizeof(DES_IV_INFO)), DESC_STATIC_STRU(7, 16), DESC_STATIC_STRU(8, 16),
  9, DESC_P_PARA(0, 2, 0), DESC_P_STRU(1, 0, 1, offsetof(KEY_PARAM, pid_list)),\
     DESC_P_STRU(1, 0, 2, offsetof(KEY_PARAM, p_aes_key_info)), DESC_P_STRU(1, 0, 3, offsetof(KEY_PARAM, p_csa_key_info)),\
     DESC_P_STRU(1, 0, 4, offsetof(KEY_PARAM, p_des_key_info)), DESC_P_STRU(1, 0, 5, offsetof(KEY_PARAM, p_aes_iv_info)),\
     DESC_P_STRU(1, 0, 6, offsetof(KEY_PARAM, p_des_iv_info)), DESC_P_STRU(1, 0, 7, offsetof(KEY_PARAM, init_vector)),\
     DESC_P_STRU(1, 0, 8, offsetof(KEY_PARAM, ctr_counter)),
  //desc of pointer ret
  0,                          
  0,
};

UINT32 sha_crypt_control[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, 64),
  1, DESC_P_PARA(0, 2, 0),
  //desc of pointer ret
  0,                          
  0,
};



void des_open(pDES_DEV pDesDev)
{
    jump_to_func(NULL, OS_hld_caller, pDesDev, DSC_NPARA(1)|FUNC_DES_OPEN, NULL);
}
void des_close(pDES_DEV pDesDev )
{
    jump_to_func(NULL, OS_hld_caller, pDesDev, DSC_NPARA(1)|FUNC_DES_CLOSE, NULL);
}

RET_CODE des_decrypt_cts(pDES_DEV pDesDev,UINT16 dmx_id,  UINT8 *input, UINT8 *output, UINT32 total_length, UINT8 *residue)
{
    UINT32 desc[] = {1, DESC_OUTPUT_STRU(0, 17),1, DESC_P_PARA(0, 5, 0), 0, 0,};
    jump_to_func(NULL, OS_hld_caller, pDesDev, DSC_NPARA(6)|FUNC_DES_DECRYPT, desc);
}

RET_CODE des_encrypt_ex(pDES_DEV pDesDev,UINT16 dmx_id,  UINT8 *input, UINT8 *output, UINT32 total_length)
{
    jump_to_func(NULL, OS_hld_caller, pDesDev, DSC_NPARA(5)|FUNC_DES_ENCRYPT, NULL);
}

RET_CODE des_decrypt(pDES_DEV pDesDev,UINT16 dmx_id,  UINT8 *input, UINT8 *output, UINT32 total_length)
{
	UINT8 residue[17];
	UINT8 times,remain;
    RET_CODE ret=RET_FAILURE;
	residue[16] = 0; 
    if((dmx_id>=0 && dmx_id<=3) || (dmx_id>=8 && dmx_id<=0xf))
    {
        if(total_length>TS_MAX_SIZE)
        {
            return ret;
        }
   		osal_cache_flush((UINT32)input, total_length*188);
		osal_cache_flush((UINT32)output, 16);
		osal_cache_flush((UINT32)output+total_length*188-16, 16);
	}
	else
	{
        if(total_length>PURE_DATA_MAX_SIZE)
        {
            return ret;
        }      
		osal_cache_flush((UINT32)input, total_length);
		if(total_length<=16)
			osal_cache_flush((UINT32)output, total_length);
		else{
			osal_cache_flush((UINT32)output, 16);
			osal_cache_flush((UINT32)output+total_length-16, 16);
		}
	}
    ret=des_decrypt_cts(pDesDev,dmx_id,input,output,total_length,residue);
	if((dmx_id>=0 && dmx_id<=3) || (dmx_id>=8 && dmx_id<=0xf))
    {
		osal_cache_invalidate((UINT32)output,  total_length*188);
	}
	else
	{
		osal_cache_invalidate((UINT32)output,  total_length);
	}   
	if(residue[16]==0x5a) //it's a flag set in SEE
	{
		remain = total_length%8+8;
		memcpy(&output[total_length-remain],residue,remain);
	}	
    return ret;
}

RET_CODE des_encrypt(pDES_DEV pDesDev,UINT16 dmx_id,  UINT8 *input, UINT8 *output, UINT32 total_length)
{
    RET_CODE ret = RET_FAILURE;
    if((dmx_id>=0 && dmx_id<=3) || (dmx_id>=8 && dmx_id<=0xf))
    {
        if(total_length>TS_MAX_SIZE)//64k
        {
            return ret;
        }        
   		osal_cache_flush((UINT32)input,  total_length*188);
		osal_cache_flush((UINT32)output, 16);
		osal_cache_flush((UINT32)output+total_length*188-16, 16);
	}
	else
	{
        if(total_length>PURE_DATA_MAX_SIZE)//64M
        {
            return ret;
        }      
		osal_cache_flush((UINT32)input, total_length);
		if(total_length<=16)
			osal_cache_flush((UINT32)output, total_length);
		else{
			osal_cache_flush((UINT32)output, 16);
			osal_cache_flush((UINT32)output+total_length-16, 16);
		}
	}
    ret=des_encrypt_ex(pDesDev,dmx_id,input,output,total_length);
	if((dmx_id>=0 && dmx_id<=3) || (dmx_id>=8 && dmx_id<=0xf))
    {
		osal_cache_invalidate((UINT32)output,  total_length*188);
	}
	else
	{
		osal_cache_invalidate((UINT32)output,  total_length);
	}
    return ret;
}


RET_CODE des_ioctl( pDES_DEV pDesDev ,UINT32 cmd , UINT32 param)
{
    UINT32 i;
    UINT32 common_desc[40];
    UINT32 *desc = (UINT32 *)common_desc;
    UINT32 *b = (UINT32 *)des_io_control;
	pKEY_PARAM param_tmp = (pKEY_PARAM)param;
    
    for(i = 0; i < sizeof(des_io_control)/sizeof(UINT32); i++)
    {
        desc[i] = b[i];
    }
    switch(cmd) 
    {
        case IO_INIT_CMD:
        {
          /*has return value*/
          DESC_STATIC_STRU_SET_SIZE(common_desc, 0, sizeof(DES_INIT_PARAM));
		  //des_dma_mode = ((pDES_INIT_PARAM)param)->dma_mode; 
		}
        break ;
        case IO_CREAT_CRYPT_STREAM_CMD :
		case IO_KEY_INFO_UPDATE_CMD:
        {
          /*has return value*/
          b = (UINT32 *)dsc_io_control_1;
          for(i = 0; i < sizeof(dsc_io_control_1)/sizeof(UINT32); i++)
          {
             desc[i] = b[i];
          }
		  
		  for(i=0; i<3; i++)
		  {
			DESC_STATIC_STRU_SET_SIZE(desc, (i+2), 2*param_tmp->pid_len*param_tmp->key_length/8);
		  }
		  DESC_STATIC_STRU_SET_SIZE(desc, 6, 2*param_tmp->pid_len*8);
		  DESC_STATIC_STRU_SET_SIZE(desc, 1, sizeof(UINT16)*param_tmp->pid_len);
        }
        break ;
        
        case IO_DELETE_CRYPT_STREAM_CMD:
        {
          /*has return value*/
          desc = NULL;
        }
        break;
     
        case IO_GET_PID_POS_CMD:
        {
           /*has return value,pos info*/
           DESC_OUTPUT_STRU_SET_SIZE(common_desc, 0, sizeof(PID_POS_PARAM));
           
        }
        break;
        default:
			if(sys_ic_get_chip_id() >= ALI_S3602F)
            return RET_FAILURE;
   }
    
    jump_to_func(NULL, OS_hld_caller, pDesDev, DSC_NPARA(3)|FUNC_DES_IOCTL, desc);
}

void aes_open(pAES_DEV pAesDev )
{
    jump_to_func(NULL, OS_hld_caller, pAesDev, DSC_NPARA(1)|(1<<16)|FUNC_AES_OPEN, NULL);
}

void aes_close(pAES_DEV pAesDev )
{
    jump_to_func(NULL, OS_hld_caller, pAesDev, DSC_NPARA(1)|FUNC_AES_CLOSE, NULL);
}
/*
RET_CODE aes_decrypt_ex(pAES_DEV pAesDev,UINT16 dmx_id,  UINT8 *input, UINT8 *output, UINT32 total_length)
{
    jump_to_func(NULL, OS_hld_caller, pAesDev, DSC_NPARA(5)|FUNC_AES_DECRYPT, NULL);
}*/

RET_CODE aes_encrypt_ex(pAES_DEV pAesDev,UINT16 dmx_id,  UINT8 *input, UINT8 *output, UINT32 total_length)
{
    jump_to_func(NULL, OS_hld_caller, pAesDev, DSC_NPARA(5)|FUNC_AES_ENCRYPT, NULL);
}


RET_CODE aes_decrypt_cts(pAES_DEV pAesDev,UINT16 dmx_id,  UINT8 *input, UINT8 *output, UINT32 total_length, UINT8 *residue)
{
    UINT32 desc[] = {1, DESC_OUTPUT_STRU(0, 33),1, DESC_P_PARA(0, 5, 0), 0, 0,};
    jump_to_func(NULL, OS_hld_caller, pAesDev, DSC_NPARA(6)|FUNC_AES_DECRYPT, desc);
}

RET_CODE aes_decrypt(pAES_DEV pAesDev,UINT16 dmx_id,  UINT8 *input, UINT8 *output, UINT32 total_length)
{
	UINT8 residue[33];
	UINT8 times,remain;
    RET_CODE ret=RET_FAILURE;
	residue[32] = 0; 
    if((dmx_id>=0 && dmx_id<=3) || (dmx_id>=8 && dmx_id<=0xf))
    {
        if(total_length>TS_MAX_SIZE)//64k
        {
            return ret;
        }          
   		osal_cache_flush((UINT32)input,  total_length*188);
		osal_cache_flush((UINT32)output, 16);
		osal_cache_flush((UINT32)output+total_length*188-16, 16);
	}
	else
	{
        if(total_length>PURE_DATA_MAX_SIZE)//64k
        {
            return ret;
        }  
		osal_cache_flush((UINT32)input, total_length);
		if(total_length<=16)
			osal_cache_flush((UINT32)output, total_length);
		else{
			osal_cache_flush((UINT32)output, 16);
			osal_cache_flush((UINT32)output+total_length-16, 16);
		}
	}
	ret = aes_decrypt_cts(pAesDev,dmx_id,input,output,total_length,residue);

	if((dmx_id>=0 && dmx_id<=3) || (dmx_id>=8 && dmx_id<=0xf))
    {
		osal_cache_invalidate((UINT32)output,  total_length*188);
	}
	else
	{
		osal_cache_invalidate((UINT32)output,  total_length);
	}
	if(residue[32]==0x5a) //it's a flag set in SEE
	{
		remain = total_length%16+16;
		memcpy(&output[total_length-remain],residue,remain);
	}	
    return ret;
}

RET_CODE aes_encrypt(pAES_DEV pAesDev, UINT16 dmx_id, UINT8 *input, UINT8 *output, UINT32 total_length)
{
    RET_CODE ret=RET_FAILURE;
    if((dmx_id>=0 && dmx_id<=3) || (dmx_id>=8 && dmx_id<=0xf))
    {
        if(total_length>TS_MAX_SIZE)//64k
        {
            return ret;
        }          
   		osal_cache_flush((UINT32)input,  total_length*188);
		osal_cache_flush((UINT32)output, 16);
		osal_cache_flush((UINT32)output+total_length*188-16, 16);
	}
	else
	{
        if(total_length>PURE_DATA_MAX_SIZE)//64k
        {
            return ret;
        }        
		osal_cache_flush((UINT32)input,  total_length);
		if(total_length<=16)
			osal_cache_flush((UINT32)output, total_length);
		else{
			osal_cache_flush((UINT32)output, 16);
			osal_cache_flush((UINT32)output+total_length-16, 16);
		}
	}
    ret=aes_encrypt_ex(pAesDev,dmx_id,input,output,total_length);
	if((dmx_id>=0 && dmx_id<=3) || (dmx_id>=8 && dmx_id<=0xf))
    {
		osal_cache_invalidate((UINT32)output,  total_length*188);
	}
	else
	{
		osal_cache_invalidate((UINT32)output,  total_length);
	}
    return ret;
}

RET_CODE aes_ioctl( pAES_DEV pAesDev ,UINT32 cmd , UINT32 param)
{
    UINT32 i;
    UINT32 common_desc[40];
    UINT32 *desc = (UINT32 *)common_desc;
    UINT32 *b = (UINT32 *)aes_io_control;
	pKEY_PARAM param_tmp = (pKEY_PARAM)param;
    
    for(i = 0; i < sizeof(aes_io_control)/sizeof(UINT32); i++)
    {
        desc[i] = b[i];
    }
    switch(cmd) 
    {
        case IO_INIT_CMD:
            DESC_STATIC_STRU_SET_SIZE(common_desc, 0, sizeof(AES_INIT_PARAM));
			//aes_dma_mode = ((pAES_INIT_PARAM)param)->dma_mode; 
        	break ;
        case IO_CREAT_CRYPT_STREAM_CMD :
		case IO_KEY_INFO_UPDATE_CMD:
        {
          /*has return value*/
          b = (UINT32 *)dsc_io_control_1;
          for(i = 0; i < sizeof(dsc_io_control_1)/sizeof(UINT32); i++)
          {
             desc[i] = b[i];
          }
		  
		  for(i=0; i<3; i++)
		  {
			DESC_STATIC_STRU_SET_SIZE(desc, (i+2), 2*param_tmp->pid_len*param_tmp->key_length/8);
		  }
		  DESC_STATIC_STRU_SET_SIZE(desc, 5, 2*param_tmp->pid_len*16);
		  DESC_STATIC_STRU_SET_SIZE(desc, 1, sizeof(UINT16)*param_tmp->pid_len);
        }
        break ;

        case IO_DELETE_CRYPT_STREAM_CMD:
            desc = NULL;
        	break;

        case IO_GET_PID_POS_CMD:  
            DESC_OUTPUT_STRU_SET_SIZE(common_desc, 0, sizeof(PID_POS_PARAM ));
        	break ;
        default:
			if(sys_ic_get_chip_id() >= ALI_S3602F)
			return RET_FAILURE;
    }
    jump_to_func(NULL, OS_hld_caller, pAesDev, DSC_NPARA(3)|FUNC_AES_IOCTL, desc);
}

void csa_open(pCSA_DEV pCsaDev)
{
    jump_to_func(NULL, OS_hld_caller, pCsaDev, DSC_NPARA(1)|FUNC_CSA_OPEN, NULL);
}

void csa_close(pCSA_DEV pCsaDev)
{
    jump_to_func(NULL, OS_hld_caller, pCsaDev, DSC_NPARA(1)|FUNC_CSA_CLOSE, NULL);
}

RET_CODE csa_decrypt_ex(pCSA_DEV pCsaDev,UINT16 dmx_id,  UINT8 *input, UINT8 *output, UINT32 total_length)
{
    jump_to_func(NULL, OS_hld_caller, pCsaDev,DSC_NPARA(5)|FUNC_CSA_DECRYPT, NULL);
}

RET_CODE csa_decrypt(pCSA_DEV pCsaDev,UINT16 dmx_id,  UINT8 *input, UINT8 *output, UINT32 total_length)
{
    RET_CODE ret=RET_FAILURE;
    if((dmx_id>=0 && dmx_id<=3) || (dmx_id>=8 && dmx_id<=0xf))
    {
        if(total_length>TS_MAX_SIZE)
        {
            return ret;
        }
   		osal_cache_flush((UINT32)input,  total_length*188);
		osal_cache_flush((UINT32)output, 16);
		osal_cache_flush((UINT32)output+total_length*188-16, 16);
	}
	else
	{
        if(total_length>PURE_DATA_MAX_SIZE)
        {
            return ret;
        }          
		osal_cache_flush((UINT32)input,  total_length);
		osal_cache_flush((UINT32)output, 16);
		osal_cache_flush((UINT32)output+total_length-16, 16);
	}
    ret=csa_decrypt_ex(pCsaDev,dmx_id,input,output,total_length);
	if((dmx_id>=0 && dmx_id<=3) || (dmx_id>=8 && dmx_id<=0xf))
    {
		osal_cache_invalidate((UINT32)output,  total_length*188);
	}
	else
	{
		osal_cache_invalidate((UINT32)output,  total_length);
	}
    return ret;
}

RET_CODE csa_ioctl( pCSA_DEV pCsaDev, UINT32 cmd, UINT32 param)
{
    UINT32 i;
    UINT32 common_desc[40];
    UINT32 *desc = (UINT32 *)common_desc;
    UINT32 *b = (UINT32 *)csa_io_control;
	pKEY_PARAM param_tmp = (pKEY_PARAM)param;
    
    for(i = 0; i < sizeof(csa_io_control)/sizeof(UINT32); i++)
    {
        desc[i] = b[i];
    }
    switch(cmd) 
    {
        case IO_INIT_CMD:
       		DESC_STATIC_STRU_SET_SIZE(common_desc, 0, sizeof(CSA_INIT_PARAM ));
		    //csa_dma_mode = ((pCSA_INIT_PARAM)param)->dma_mode; 
	     	break ;
        case IO_CREAT_CRYPT_STREAM_CMD :
		case IO_KEY_INFO_UPDATE_CMD:
        {
          /*has return value*/
          b = (UINT32 *)dsc_io_control_1;
          for(i = 0; i < sizeof(dsc_io_control_1)/sizeof(UINT32); i++)
          {
             desc[i] = b[i];
          }
		  
		  for(i=0; i<3; i++)
		  {
			DESC_STATIC_STRU_SET_SIZE(desc, (i+2), 2*param_tmp->pid_len*param_tmp->key_length/8);
		  }
		  DESC_STATIC_STRU_SET_SIZE(desc, 1, sizeof(UINT16)*param_tmp->pid_len);
        }
        break ;

        case IO_DELETE_CRYPT_STREAM_CMD:
        	desc = NULL;
          break;
		  
        case IO_GET_PID_POS_CMD:
        DESC_OUTPUT_STRU_SET_SIZE(common_desc, 0, sizeof(PID_POS_PARAM ));
        break ;

        default:
			if(sys_ic_get_chip_id() >= ALI_S3602F)
            return RET_FAILURE;
    }
    jump_to_func(NULL, OS_hld_caller, pCsaDev, DSC_NPARA(3)|FUNC_CSA_IOCTL, desc);
}


void sha_open(pSHA_DEV pShaDev)
{
    jump_to_func(NULL, OS_hld_caller, pShaDev, DSC_NPARA(1)|FUNC_SHA_OPEN, NULL);
}

void sha_close(pSHA_DEV pShaDev)
{
    jump_to_func(NULL, OS_hld_caller, pShaDev, DSC_NPARA(1)|FUNC_SHA_CLOSE, NULL);
}

RET_CODE sha_ioctl( pSHA_DEV pShaDev ,UINT32 cmd , UINT32 param)
{
    UINT32 i;
    UINT32 common_desc[sizeof(sha_io_control)];
    UINT32 *desc = (UINT32 *)common_desc;
    UINT32 *b = (UINT32 *)sha_io_control;
    
    for(i = 0; i < sizeof(sha_io_control)/sizeof(UINT32); i++)
    {
        desc[i] = b[i];
    }
    switch(cmd)
    {
       case IO_INIT_CMD:
       {
         DESC_STATIC_STRU_SET_SIZE(common_desc, 0, sizeof(SHA_INIT_PARAM ));
       }
       break;

       default:
        if(sys_ic_get_chip_id() >= ALI_S3602F)
       	return RET_FAILURE;
    }
    jump_to_func(NULL, OS_hld_caller, pShaDev, DSC_NPARA(3)|FUNC_SHA_IOCTL, desc);
}

RET_CODE sha_digest_ex(pSHA_DEV pShaDev, UINT8 *input, UINT8 *output,UINT32 data_length)
{
    jump_to_func(NULL, OS_hld_caller, pShaDev, DSC_NPARA(4)|FUNC_SHA_DIGEST, sha_crypt_control);
}


RET_CODE sha_digest(pSHA_DEV pShaDev, UINT8 *input, UINT8 *output,UINT32 data_length)
{
    RET_CODE ret=RET_FAILURE;
    if(data_length>PURE_DATA_MAX_SIZE)
    {
        return ret;
    }        
    osal_cache_flush((UINT32)input,data_length);
    ret=sha_digest_ex(pShaDev,input,output,data_length);   
    return ret;
}

UINT32 dsc_bl_ctrl[] = 
{ //desc of pointer para
  2, DESC_OUTPUT_STRU(0, sizeof(DSC_BL_UK_PARAM)), DESC_OUTPUT_STRU(1, 16),
  2, DESC_P_PARA(0, 2, 0),
  DESC_P_STRU(1, 0, 1, offsetof(DSC_BL_UK_PARAM, output_key)),
  //desc of pointer ret
  0,                          
  0,
};


RET_CODE dsc_ioctl( pDSC_DEV pDscDev ,UINT32 cmd , UINT32 param)
{

    UINT32 i;
    //UINT32 common_desc[sizeof(dsc_io_control)];
	UINT32 common_desc[40];
    UINT32 *desc = (UINT32 *)common_desc;
    UINT32 *b = (UINT32 *)dsc_io_control;
    
    for(i = 0; i < sizeof(dsc_io_control)/sizeof(UINT32); i++)
    {
        desc[i] = b[i];
    }

    switch(cmd)
    {
        case IO_PARSE_DMX_ID_GET_CMD:
            DESC_OUTPUT_STRU_SET_SIZE(common_desc, 0, sizeof(UINT32));
            break;

        case IO_PARSE_DMX_ID_SET_CMD:
            desc = NULL ;
            break;
        case IO_DSC_GET_DES_HANDLE:
            DESC_OUTPUT_STRU_SET_SIZE(common_desc, 0, sizeof(UINT32));
             break;
        case IO_DSC_GET_AES_HANDLE:
            DESC_OUTPUT_STRU_SET_SIZE(common_desc, 0, sizeof(UINT32));
             break;
        case IO_DSC_GET_CSA_HANDLE:
            DESC_OUTPUT_STRU_SET_SIZE(common_desc, 0, sizeof(UINT32));
             break;
        case IO_DSC_GET_SHA_HANDLE:
            DESC_OUTPUT_STRU_SET_SIZE(common_desc, 0, sizeof(UINT32));
             break;
        case IO_DSC_SET_PVR_KEY_PARAM:
            DESC_STATIC_STRU_SET_SIZE(common_desc, 0, sizeof(DSC_PVR_KEY_PARAM));
             break;
        case IO_DSC_ENCRYTP_BL_UK:
              /*has return value*/
              b = (UINT32 *)dsc_bl_ctrl;
              for(i = 0; i < sizeof(dsc_bl_ctrl)/sizeof(UINT32); i++)
              {
                 desc[i] = b[i];
              }
              break;   
        case IO_DSC_SET_PVR_KEY_IDLE:
            desc = NULL;
            break;   
		case IO_DSC_SET_ENCRYPT_PRIORITY:                 
			DESC_STATIC_STRU_SET_SIZE(common_desc, 0, sizeof(DSC_EN_PRIORITY));
			break;    	
        default:
            break;
    }

    jump_to_func(NULL, OS_hld_caller, pDscDev, DSC_NPARA(3)|FUNC_DSC_IOCTL, desc);

}

RET_CODE dsc_des_decrypt_cw_data(UINT8 cw_pos,UINT8 *in_data, UINT8 *out_data, UINT32 length)
{
    jump_to_func(NULL, OS_hld_caller, cw_pos,DSC_NPARA(4)|FUNC_DES_DECRYPT_CW_DATA, NULL);
}

RET_CODE trig_ram_mon_ex(UINT32 start_addr,UINT32 end_addr, UINT32 interval, enum SHA_MODE sha_mode,BOOL DisableOrEnable)
{
	jump_to_func(NULL, OS_hld_caller, start_addr,DSC_NPARA(5)|FUNC_TRIG_RAM_MON, NULL);
}

RET_CODE trig_ram_mon(UINT32 start_addr,UINT32 end_addr, UINT32 interval, enum SHA_MODE sha_mode,BOOL DisableOrEnable)
{
    static UINT32 ram_mon_enabled = 0;
    RET_CODE ret = RET_FAILURE;
    if(ram_mon_enabled ==0 )
    {
	    ret = trig_ram_mon_ex(start_addr,end_addr,interval,sha_mode,DisableOrEnable);
        ram_mon_enabled = 1;
    }
    return ret;
}

RET_CODE DeEncrypt_ex(pDEEN_CONFIG p_DeEn,UINT8 *input,UINT8 *output , UINT32 total_length)
{
     UINT32 desc[] = {1,DESC_STATIC_STRU(0, sizeof(DEEN_CONFIG)),1,DESC_P_PARA(0,0,0),0,0,};
	 jump_to_func(NULL, OS_hld_caller, p_DeEn,DSC_NPARA(4)|FUNC_DEENCRYPT, desc);
}

RET_CODE DeEncrypt(pDEEN_CONFIG p_DeEn,UINT8 *input,UINT8 *output , UINT32 total_length)
{
    RET_CODE ret = RET_FAILURE;
    if(total_length>TS_MAX_SIZE)
    {
        return ret;
    }        
	osal_cache_flush((UINT32)input,  total_length*188);
    ret = DeEncrypt_ex(p_DeEn,input,output,total_length);
	osal_cache_invalidate((UINT32)output,  total_length*188);
}
UINT16 dsc_get_free_stream_id(enum DMA_MODE dma_mode)
{
	 jump_to_func(NULL, OS_hld_caller, dma_mode,DSC_NPARA(1)|FUNC_GET_FREE_STREAM_ID, NULL);
}
UINT32 dsc_get_free_sub_device_id(enum WORK_SUB_MODULE sub_mode)
{
	 jump_to_func(NULL, OS_hld_caller, sub_mode,DSC_NPARA(1)|FUNC_GET_FREE_SUB_DEVICE_ID, NULL);
}
RET_CODE dsc_set_sub_device_id_idle(enum WORK_SUB_MODULE sub_mode,UINT32 device_id)
{
	 jump_to_func(NULL, OS_hld_caller, sub_mode,DSC_NPARA(2)|FUNC_SET_SUB_DEVICE_ID_IDLE, NULL);
}
RET_CODE dsc_set_stream_id_idle(UINT32 pos) 
{
	 jump_to_func(NULL, OS_hld_caller, pos,DSC_NPARA(1)|FUNC_SET_STREAM_ID_IDLE, NULL);
}    

void dsc_set_stream_id_used(UINT32 pos) 
{
	 jump_to_func(NULL, OS_hld_caller, pos,DSC_NPARA(1)|FUNC_SET_STREAM_ID_USED, NULL);
} 
RET_CODE dsc_set_sub_device_id_used(enum WORK_SUB_MODULE sub_mode,UINT32 device_id)
{
	 jump_to_func(NULL, OS_hld_caller, sub_mode,DSC_NPARA(2)|FUNC_SET_SUB_DEVICE_ID_USED, NULL);
}

RET_CODE dsc_deal_quantum_for_mixed_ts(pDEEN_CONFIG p_DeEn, UINT32 temp_length)
{
	 jump_to_func(NULL, OS_hld_caller, p_DeEn ,DSC_NPARA(2)|FUNC_DEAL_QUANTUM_MIXED_TS, NULL);
}

#endif  /*_HLD_DSC_REMOTE*/

#endif  /*DUAL_ENABLE*/

/* 
   crypt_mode -> 0 encrypt
   crypt_mode -> 1 decrypt 
*/
RET_CODE aes_pure_ecb_crypt( UINT8 *key, UINT8 *input, 
							UINT8 *output, UINT32 length, 
							UINT8 crypt_mode)
{
	int ret = RET_FAILURE;
	UINT32 stream_id = INVALID_DSC_STREAM_ID;
	pAES_DEV pAesDev = NULL;
	struct aes_init_param aes_param;
	KEY_PARAM key_param;
	AES_KEY_PARAM key_info[1];
	UINT16 pid[1] = {0x1234};

	UINT32 device_id = dsc_get_free_sub_device_id(AES);
	if(device_id == INVALID_DSC_SUB_DEV_ID)
		return ret;
	pAesDev = (pAES_DEV)dev_get_by_id(HLD_DEV_TYPE_AES, device_id);

	if ((stream_id = dsc_get_free_stream_id(PURE_DATA_MODE)) == \
		INVALID_DSC_STREAM_ID)
	{
		goto DONE1;
	}

	memset( &aes_param, 0, sizeof ( struct aes_init_param ) );
	aes_param.dma_mode = PURE_DATA_MODE;
	aes_param.key_from = KEY_FROM_SRAM;
	aes_param.key_mode = AES_128BITS_MODE ;
	aes_param.parity_mode = EVEN_PARITY_MODE;
	aes_param.residue_mode = RESIDUE_BLOCK_IS_NO_HANDLE ;
	aes_param.scramble_control = 0 ;
	aes_param.stream_id = stream_id;
	aes_param.work_mode = WORK_MODE_IS_ECB ;
	ret=aes_ioctl ( pAesDev , IO_INIT_CMD , ( UINT32 ) &aes_param );
	if(ret != RET_SUCCESS)
	{
		goto DONE2;
	}

	memset(&key_param, 0, sizeof(KEY_PARAM));
	memcpy(key_info[0].aes_128bit_key.even_key, key, 16);
	key_param.handle = 0xFF ;
	key_param.ctr_counter = NULL; 
	key_param.init_vector = NULL;
	key_param.key_length = 128;  
	key_param.pid_len = 1;				
	key_param.pid_list = pid;			
	key_param.p_aes_key_info = key_info;
	key_param.stream_id = stream_id;
	ret=aes_ioctl (pAesDev,IO_CREAT_CRYPT_STREAM_CMD, (UINT32)&key_param);
	if(ret != RET_SUCCESS)
	{
		goto DONE2;
	}

	if(crypt_mode == 0)
		ret = aes_encrypt( pAesDev, stream_id, input, output, length );
	else
		ret = aes_decrypt( pAesDev, stream_id, input, output, length );

DONE3:
	aes_ioctl( pAesDev, IO_DELETE_CRYPT_STREAM_CMD , key_param.handle);
DONE2:
	dsc_set_stream_id_idle(stream_id);
DONE1:
	dsc_set_sub_device_id_idle(AES, device_id);
	return ret;
}


